

#include "entity.h"
#include "images_diffuse.h"
#include "bullet.h"
#include "hitbox.h"
#include "tag.h"
#include "explosions.h"
#include "enemy.h"
#include "hitpoint.h"
#include "random.h"

#define PERIOD 400

#include <math.h>

declare_body(mothership, {
	size_t period;
	size_t b_period;
	float time;
})

float sin_n(float t) {
	return (1 + sin(t)) / 2;
}

entity *sat(entity *ship, vec pos) {
	entity *ent = make_satellite(pos, 3);
	ent->position = vadd(ship->position, vxy(32, 32));
	return ent;
}

void spray(entity *ship, vec pos) {
	entity *ent = make_basic_spray(pos, 5);
	ent->position = vadd(ship->position, vxy(32, 32));
}

void tri(entity *ship, vec pos) {
	entity *ent = make_triangle(pos, 16);
	ent->position = vadd(ship->position, vxy(32, 32));
}

void cyc(entity *ship, vec pos) {
	entity *ent = make_cycle(pos, 12);
	ent->position = vadd(ship->position, vxy(32, 32));
}

void mis(entity *ship, vec pos) {
	entity *ent = make_missile(pos, 13);
	ent->position = vadd(ship->position, vxy(32, 32));
}

void spawn_sat_3(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	sat(ship, target);
	sat(ship, vadd(target, vx(20)));
	sat(ship, vsub(target, vx(20)));
}

void spawn_sat_5(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	sat(ship, target);
	sat(ship, vadd(target, vx(20)));
	sat(ship, vsub(target, vx(20)));
	sat(ship, vadd(target, vx(40)));
	sat(ship, vsub(target, vx(40)));
}

void spawn_sat_spray(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	sat(ship, vadd(target, vx(10)));
	sat(ship, vadd(target, vx(-10)));
	spray(ship, vadd(target, vxy(0, -15)));
	spray(ship, vadd(target, vx(-20)));
	spray(ship, vadd(target, vx(20)));
}

void spawn_triangle_2(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	tri(ship, vadd(target, vx(-16)));
	tri(ship, vadd(target, vx(16)));
}

void spawn_triangle_3(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	tri(ship, vadd(target, vx(-20)));
	tri(ship, vadd(target, vx(20)));
	tri(ship, vadd(target, vxy(0, -5)));
}

void spawn_cycle_2(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	cyc(ship, vadd(target, vx(-16)));
	cyc(ship, vadd(target, vx(16)));
}

void spawn_missile(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	mis(ship, target);
}

void spawn_mis_cyc(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	mis(ship, target);
	cyc(ship, vadd(target, vx(-40)));
	cyc(ship, vadd(target, vx(40)));
}

void spawn_spray_cyc(entity *ship) {
	vec target = vadd(ship->position, vxy(32, -15));
	cyc(ship, target);
	spray(ship, vadd(target, vx(-10)));
	spray(ship, vadd(target, vx(10)));
}

typedef void (*spawner)(entity*);

spawner spawners[] = {
	&spawn_sat_3,
	&spawn_sat_5,
	&spawn_sat_spray,
	&spawn_triangle_2,
	&spawn_triangle_3,
	&spawn_cycle_2,
	&spawn_missile,
	&spawn_mis_cyc,
	&spawn_spray_cyc
};

#define SPAWNERCOUNT (sizeof(spawners) / sizeof(spawners[0]))

size_t inde() {
	float i = rand_range(0, SPAWNERCOUNT);
	size_t in = (size_t) i;
	if(in >= SPAWNERCOUNT) in = SPAWNERCOUNT - 1;
	return in;
}



size_t spawner_cost[] = {
	80+50,
	90+50,
	220+50,
	390+50,
	410+40,
	350+50,
	200+50,
	400+50,
	430+50
};

extern entity *player;

declare_tick(mothership, {
	parent->position.x = 136 * sin_n(self->time);
	self->time += 0.0006f;
	
	if(self->period == 0) {
		size_t ind = inde();
		self->period = spawner_cost[ind];
		
		spawners[ind](parent);
	}
	else --self->period;
	
	if(self->b_period) --self->b_period;
	else {
		vec b1 = vadd(parent->position, vxy(10, 30));
		vec b2 = vadd(parent->position, vxy(60, 30));
		vec v1 = vsub(player->position, b1);
		vec v2 = vsub(player->position, b2);
		
		v1 = vmul(normalize(v1), 7.f);
		v2 = vmul(normalize(v2), 7.f);
		
		make_enemy_bullet(
			get_animator_c(&sprite_mothership_bullet, 2, vxy(2.5f, 0)),
			b1,
			v1,
			NULL
		);
		make_enemy_bullet(
			get_animator_c(&sprite_mothership_bullet, 2, vxy(2.5f, 0)),
			b2,
			v2,
			NULL
		);
		self->b_period = 40;
	}
})

declare_draw(mothership, { })

declare_head(mothership)

entity *make_mothership(vec location) {
	entity *ent = ent_new();
	ent->position = vxy(location.x, 250);
	ent->tag = TAG_ENEMY;
	
	mothership *b = c_new(mothership);
	b->period = 60; /* Delay basically until we on onscreen but fire quickly */
	b->time = 0;
	b->b_period = 0;
	
	add_component(ent, get_renderer(&sprite_mothership));
	add_component(ent, b);
	add_component(ent, target_loc(location));
	
	for(int x = 21; x <= 41; x += 3) {
		for(int y = 6; y <= 50; y += 3) {
			add_hitpoint(ent, vxy(x, y));
		}
	}
	
	add_hitbox(ent, 20, 25, 23, 27);
	
	return ent;
}